<?php

declare(strict_types=1);

namespace App\Controller\Admin\V1\Admin;

use App\Controller\Admin\V1\Controllers;
use App\Request\Admin\Menu as MenuRequest;
use App\Services\Admin\Menu as MenuServices;
use Hyperf\Database\Model\Relations\HasMany;
use Hyperf\DbConnection\Db;
use function Hyperf\Translation\__;

class Menu extends Controllers
{
    /**
     * 验证类
     * @var string
     */
    protected string $requestClass = MenuRequest::class;

    public function __construct(MenuServices $menuServices)
    {
        parent::__construct();

        $this->services = $menuServices;
    }

    /**
     * 分页
     * @return \Psr\Http\Message\ResponseInterface
     */
    public function index()
    {
        $input = $this->input(['app']);
        $lists = $this->services
            ->where('parent_id', 0)
            ->where('app', $input['app'])
            ->with(['children' => function(HasMany $hasMany){
                $hasMany->with(['children' => function (HasMany $hasMany) {
                    $hasMany->with(['permission']);
                }]);
            }])
            ->orderBy('sort', 'desc')
            ->get();

        return success($lists);
    }

    /**
     * 添加
     * @param MenuRequest $request
     * @return \Psr\Http\Message\ResponseInterface
     */
    public function save()
    {
        $request = $this->container->get(MenuRequest::class);
        $request->scene('save')->validateResolved();
        $input = $request->only([
            'parent_id',
            'name',
            'icon',
            'path',
            'status',
            'desc',
            'app'
        ]);
        $input['level'] = 1;
        if ($input['parent_id'] > 0) {
            $parentMenuServices = $this->services->findOrFail($input['parent_id']);
            if ($parentMenuServices->level >= 3) {
                return failed(__('message.level.parent', [
                    'name' => __('model.table.menu'),
                    'level'=>2,
                    'contrast' => __('character.gt')
                ]));
            }
            $input['level'] = $parentMenuServices->level+1;
        }
        $model = $this->services->create($input);
        if (!$model->exists) {
            return internalError(__('message.stored.failed'));
        }
        return stored();
    }

    /**
     * 编辑
     * @param int $id
     * @return \Psr\Http\Message\ResponseInterface
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    public function update(int $id)
    {
        $request = $this->container->get(MenuRequest::class);
        $request->scene('update')->validateResolved();
        $input = $request->only([
            'parent_id',
            'name',
            'icon',
            'path',
            'status',
            'desc',
            'app'
        ]);
        $model = $this->services->findOrFail($id);
        $input['level'] = 1;
        if ($input['parent_id'] > 0) {
            $parentMenuServices = $this->services->findOrFail($input['parent_id']);
            if ($parentMenuServices->level >= 3) {
                return failed(__('message.level.parent', [
                    'name' => __('model.table.menu'),
                    'level'=>2,
                    'contrast' => __('character.gt')
                ]));
            }
            $input['level'] = $parentMenuServices->level+1;
        }
        if (!$model->fill($input)->save()) {
            return internalError(__('message.updated.failed'));
        }

        return updated();
    }

    /**
     * 批量删除
     * @return \Psr\Http\Message\ResponseInterface
     * @throws \Exception
     */
    public function destroy()
    {
        $request = $this->container->get(MenuRequest::class);
        $request->scene('destroy')->validateResolved();
        $input = $request->only(['ids']);

        $models = $this->services->whereIn('id', $input['ids'])->with(['children'])->get();

        Db::beginTransaction();
        foreach ($models as $model) {
            if (!$model->children->isEmpty()) {
                Db::rollBack();
                return failed(__('message.destroy.children.exists'));
            }
            $model->delete();
        }

        Db::commit();
        return deleted();
    }

    /**
     * 排序
     * @param int $id
     * @return \Psr\Http\Message\ResponseInterface
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    public function sort(int $id)
    {
        $request = $this->container->get(MenuRequest::class);
        $request->scene('sort')->validateResolved();
        $model = $this->services->findOrFail($id);
        $input = $request->only(['id/d']);

        $res = $this->services->sort($model, $input['id'], 'parent_id');
        if (!$res) {
            return internalError(__('message.sort.failed'));
        }
        return updated();
    }

}
